package com.example.opengldemo._camera_demo;

import android.graphics.Point;
import android.graphics.SurfaceTexture;
import android.opengl.EGL14;
import android.opengl.GLES30;

import com.example.opengldemo._camera_demo.buffer.FrameBuffer;
import com.example.opengldemo._camera_demo.core.IObserver;
import com.example.opengldemo._camera_demo.core.Observable;
import com.example.opengldemo._camera_demo.core.Renderer;
import com.example.opengldemo._camera_demo.egl.EGLConfigAttrs;
import com.example.opengldemo._camera_demo.egl.EGLContextAttrs;
import com.example.opengldemo._camera_demo.egl.EglHelper;
import com.example.opengldemo._camera_demo.provider.ITextureProvider;
import com.example.opengldemo._camera_demo.renderer.RenderBean;
import com.example.opengldemo.util.TextureUtil;

public class VideoSurfaceProcessor {
    private boolean mGLThreadFlag=false;
    private Thread mGLThread;
    private Renderer renderer;
    private boolean isRendererChanged = false;
    private Observable<RenderBean> observable;
    private final Object LOCK=new Object();

    private ITextureProvider mProvider;

    public VideoSurfaceProcessor(){
        observable=new Observable<>();
    }

    public void setTextureProvider(ITextureProvider provider){
        this.mProvider=provider;
    }
    public void start(){
        synchronized (LOCK){
            if(!mGLThreadFlag){
                if(mProvider==null){
                    return;
                }
                mGLThreadFlag=true;
                mGLThread=new Thread(new Runnable() {
                    @Override
                    public void run() {
                        glRun();
                    }
                });
                mGLThread.start();
                try {
                    LOCK.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    public void stop(){
        synchronized (LOCK){
            if(mGLThreadFlag){
                mGLThreadFlag=false;
                mProvider.close();
                try {
                    LOCK.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }



    private void glRun(){
        //获取EGL
        EglHelper egl=new EglHelper();
        // 创建一个环境
        boolean ret=egl.createGLESWithSurface(new EGLConfigAttrs(),new EGLContextAttrs(),new SurfaceTexture(1));
        if(!ret){
            //todo 错误处理
            return;
        }
        //获取一个纹理 屏幕的纹理
        int mInputSurfaceTextureId = TextureUtil.createTextureID(true);
        //通过纹理设置一个surface
        SurfaceTexture mInputSurfaceTexture = new SurfaceTexture(mInputSurfaceTextureId);
        //打开该对象
        Point size=mProvider.open(mInputSurfaceTexture);
        if(size.x<=0||size.y<=0){
            //todo 错误处理
            destroyGL(egl);
            synchronized (LOCK){
                LOCK.notifyAll();
            }
            return;
        }
        // 获取到长宽
        int mSourceWidth = size.x;
        int mSourceHeight = size.y;
        //加锁
        synchronized (LOCK){
            LOCK.notifyAll();
        }
        //新建一个renderer
        WrapRenderer wrapRenderer=new WrapRenderer(null);
        wrapRenderer.create();
        wrapRenderer.sizeChanged(mSourceWidth,mSourceHeight);
        wrapRenderer.setFlag(mProvider.isLandscape()?WrapRenderer.TYPE_CAMERA:WrapRenderer.TYPE_MOVE);
        //新建帧缓存
        FrameBuffer sourceFrame=new FrameBuffer();
        //用于其他的回调
        RenderBean rb=new RenderBean();
        rb.egl=egl;
        rb.sourceWidth= mSourceWidth;
        rb.sourceHeight= mSourceHeight;
        rb.endFlag=false;
        rb.threadId=Thread.currentThread().getId();
        //要求数据源必须同步填充SurfaceTexture，填充完成前等待
        // 获取一帧数据 确定不是最后一帧
        while (!mProvider.frame()&&mGLThreadFlag){
            //检查renderer
            wrapRenderer = checkWrapRenderer(wrapRenderer,mSourceWidth,mSourceHeight);
            //输入纹理进行请求刷新
            mInputSurfaceTexture.updateTexImage();
            // 获取其
            mInputSurfaceTexture.getTransformMatrix(wrapRenderer.getTextureMatrix());

            sourceFrame.bindFrameBuffer(mSourceWidth, mSourceHeight);
            GLES30.glViewport(0,0, mSourceWidth, mSourceHeight);
            wrapRenderer.draw(mInputSurfaceTextureId);
            sourceFrame.unBindFrameBuffer();

            rb.textureId=sourceFrame.getCacheTextureId();
            //接收数据源传入的时间戳
            rb.timeStamp=mProvider.getTimeStamp();
            rb.textureTime= mInputSurfaceTexture.getTimestamp();
            observable.notify(rb);
        }
        synchronized (LOCK){
            rb.endFlag=true;
            observable.notify(rb);
            wrapRenderer.destroy();
            destroyGL(egl);
            LOCK.notifyAll();
        }
    }

    private WrapRenderer checkWrapRenderer(WrapRenderer renderer,int width,int height){
        if(isRendererChanged){
            isRendererChanged = false;
            renderer.destroy();
            renderer = new WrapRenderer(this.renderer);
            renderer.create();
            renderer.sizeChanged(width, height);
            renderer.setFlag(mProvider.isLandscape()?WrapRenderer.TYPE_CAMERA:WrapRenderer.TYPE_MOVE);
        }
        return renderer;
    }

    private void destroyGL(EglHelper egl){
        mGLThreadFlag=false;
        EGL14.eglMakeCurrent(egl.getDisplay(), EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_CONTEXT);
        EGL14.eglDestroyContext(egl.getDisplay(),egl.getDefaultContext());
        EGL14.eglTerminate(egl.getDisplay());
    }

    public void addObserver(IObserver<RenderBean> observer) {
        observable.addObserver(observer);
    }
    public void setRenderer(Renderer renderer){
        // 设置renderer 后 设置renderer 改变标识为true
        this.renderer = renderer;
        this.isRendererChanged = true;
    }
}
